<template>
	<div class="bear-SizeObserver">
		<div v-if="!observer"
			 ref="expand"
			 class="bear-expand"
			 @scroll.passive="$_bear_scrollFn">
			<div></div>
		</div>
		<div v-if="!observer"
			 ref="shrink"
			 class="bear-shrink"
			 @scroll.passive="$_bear_scrollFn">
			<div></div>
		</div>
		<slot></slot>
	</div>
</template>

<script>
	/**
	 * @author 唐国雄
	 * 可以监听大小变化的容器
	 * 属性----------------------
	 * v-model			容器大小对象,仅用做监听{width:<Number>,height:<Number>}
	 * 事件----------------------
	 * @bear-resize		容器大小改变
	 * 全局事件总线----------------------
	 * globalEvent.SizeObserver	兼容不支持ResizeObserver时,初始化时隐藏,在第一次显示时调用
	 *
	 * @typedef SizeObserver
	 * @event SizeObserver#bear-resize
	 * @type {SizeInfo} 当前容器的大小信息
	 */
	/**
	 * 大小信息
	 * @typedef SizeInfo
	 * @property {Number} width 宽
	 * @property {Number} height 高
	 */
	import {globalEvent} from './common';
	export default{
		name:'SizeObserver',
		data(){
			const data={};
			if(window.ResizeObserver){
				data.observer=new ResizeObserver(entries => {
					const target=entries[0].target;
					const sizeObj={
						width:target.offsetWidth,
						height:target.offsetHeight
					};
					this.$emit('bear-resize',sizeObj);
					this.$emit('input',sizeObj);
				});
			}else{
				// 解决ie的bug必须先设置为固定大小,mounted以后取消设置
				data.observer=null;
			}
			return data;
		},
		mounted(){
			if(this.observer){
				this.observer.observe(this.$el,{box:'border-box'});
			}else{
				globalEvent.$once(globalEvent.SizeObserver,() => {
					const refs=this.$refs;
					refs.expand.scrollLeft=refs.shrink.scrollLeft=this.maxWidth;
					refs.expand.scrollTop=refs.shrink.scrollTop=this.maxHeight;
				});
				// 值太大后ie出bug
				const maxWidth=1e7;
				const maxHeight=1e7;
				this.maxWidth=maxWidth;
				this.maxHeight=maxHeight;
				const refs=this.$refs;
				const expandChild=refs.expand.firstElementChild;
				requestAnimationFrame(function(){
					expandChild.style.width=maxWidth+'px';
					expandChild.style.height=maxHeight+'px';
					refs.expand.scrollLeft=refs.shrink.scrollLeft=maxWidth;
					refs.expand.scrollTop=refs.shrink.scrollTop=maxHeight;
				});
			}
		},
		beforeDestroy(){
			if(this.observer){
				this.observer.disconnect();
			}
		},
		methods:{
			$_bear_scrollFn(e){
				requestAnimationFrame(() => {
					const curEle=this.$el;
					const width=curEle.offsetWidth;
					const height=curEle.offsetHeight;
					if(width!==this.lastWidth||height!==this.lastHeight){
						this.lastWidth=width;
						this.lastHeight=height;
						const sizeObj={
							width:width,
							height:height
						};
						this.$emit('bear-resize',sizeObj);
						this.$emit('input',sizeObj);
						const refs=this.$refs;
						refs.expand.scrollLeft=refs.shrink.scrollLeft=this.maxWidth;
						refs.expand.scrollTop=refs.shrink.scrollTop=this.maxHeight;
					}
				});
			}
		}
	};
</script>

<style lang="scss">
	.bear-SizeObserver{
		position:relative;
		>.bear-expand,>.bear-shrink{
			position:absolute;
			top:0;
			bottom:0;
			left:0;
			right:0;
			z-index:-10000;
			overflow:hidden;
			visibility:hidden;
			>div{
				transition:0s;
				animation:none;
			}
		}
		>.bear-shrink{
			>div{
				width:200%;
				height:200%;
			}
		}
	}
</style>
